﻿// <copyright file="XamlHandler.cs" company="Snowman Consulting">
//     Copyright (c) 2009 Snowman Consulting. All rights reserved.
// </copyright>

namespace SnowmanConsulting.ProductKeyManager.Xml
{
    using System;
    using System.IO;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Xml.Linq;
    using SnowmanConsulting.ProductKeyManager.Data;

    /// <summary>
    /// XAML hanlder
    /// </summary>
    public class XamlHandler : IXmlHandler
    {
        /// <summary>
        /// prroduct collection
        /// </summary>
        private ProductCollection products;

        /// <summary>
        /// generated xml
        /// </summary>
        private string generatedXml;

        /// <summary>
        /// Gets the Products imported from the XML.
        /// </summary>
        /// <value>The Products.</value>
        public ProductCollection Products
        {
            get { return this.products; }
            private set { this.products = value; }
        }

        /// <summary>
        /// Gets the XML generated by from the Products.
        /// </summary>
        /// <value>The generated XML.</value>
        public string GeneratedXml
        {
            get { return this.generatedXml; }
        }

        /// <summary>
        /// Imports the XML.
        /// </summary>
        /// <param name="fileUri">The file URI.</param>
        public void Load(Uri fileUri)
        {
            XDocument document = XDocument.Load(fileUri.ToString());
            this.Load(document);
        }

        /// <summary>
        /// Imports the XML.
        /// </summary>
        /// <param name="xml">The XML document.</param>
        public void Load(string xml)
        {
            XDocument document = XDocument.Load(new StringReader(xml));
            this.Load(document);
        }

        /// <summary>
        /// Imports the XML.
        /// </summary>
        /// <param name="xmlDocument">The XML document.</param>
        public void Load(XDocument xmlDocument)
        {
            this.products = null;
            XElement xmlTextBlock = xmlDocument.Descendants().Last();
            string xmlText = xmlTextBlock.Attribute("Text").Value;

            ProductKeyManagerXmlHandler pkmHandler = new ProductKeyManagerXmlHandler();
            pkmHandler.Load(xmlText);
            this.Products = pkmHandler.Products;
        }

        /// <summary>
        /// Generates the XML.
        /// </summary>
        /// <param name="productCollection">The Products.</param>
        public void GenerateXml(ProductCollection productCollection)
        {
            this.GenerateXml(productCollection, false, string.Empty);
        }

        /// <summary>
        /// Generates the XML.
        /// </summary>
        /// <param name="productCollection">The Products.</param>
        /// <param name="generateStyleSheet">if set to <c>true</c> the stylesheet is generated.</param>
        /// <param name="fileName">Name of the file.</param>
        public void GenerateXml(ProductCollection productCollection, bool generateStyleSheet, string fileName)
        {
            XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
            string xmlResult = String.Empty;
            XElement xml = new XElement(
                ns + XamlType.Page,
                new XAttribute(XNamespace.Xmlns + "x", "http://schemas.microsoft.com/winfx/2006/xaml"),
                GeneratePageResources(ns),
                GenerateScrollViewer(productCollection, ns));

            this.generatedXml = xmlResult + xml.ToString();
        }

        /// <summary>
        /// Generates the scroll viewer.
        /// </summary>
        /// <param name="productCollection">The product collection.</param>
        /// <param name="ns">The namespace.</param>
        /// <returns>The scroll viewer XElement</returns>
        private static XElement GenerateScrollViewer(ProductCollection productCollection, XNamespace ns)
        {
            ProductKeyManagerXmlHandler pkmHandler = new ProductKeyManagerXmlHandler();
            pkmHandler.GenerateXml(productCollection);

            return new XElement(
                ns + XamlType.ScrollViewer,
                new XElement(ns + XamlType.StackPanel, GenerateProducts(productCollection, ns), new XElement(ns + XamlType.TextBlock, new XAttribute("Text", pkmHandler.GeneratedXml), new XAttribute("Visibility", "Collapsed"))));

            // FLAG
        }

        /// <summary>
        /// Generates the page resources.
        /// </summary>
        /// <param name="ns">The namespace.</param>
        /// <returns>The page resources XElement</returns>
        private static XElement GeneratePageResources(XNamespace ns)
        {
            return new XElement(
                ns + XamlType.PageResources,
                XamlGenerator.GeneratePanelBackgroundStyle(ns),
                XamlGenerator.GenerateKeyAllocatedLabelStyles(ns));
        }

        /// <summary>
        /// Generates the products.
        /// </summary>
        /// <param name="products">The products.</param>
        /// <param name="ns">The namespace.</param>
        /// <returns>An IEnumerable collection of XElements that make up the XAML for the products</returns>
        private static System.Collections.Generic.IEnumerable<XElement> GenerateProducts(ProductCollection products, XNamespace ns)
        {
            return from p in products
                   select new XElement(
                       ns + XamlType.DockPanel,
                       GenerateNameStackPanel(ns, p),
                       GenerateNotesStackPanel(ns, p),
                       GenerateProductKeysStackPanel(ns, p));
        }

        /// <summary>
        /// Generates the product keys scroll viewer.
        /// </summary>
        /// <param name="ns">The namespace.</param>
        /// <param name="product">The product.</param>
        /// <returns>The Product Keys Scroll Viewer</returns>
        private static XElement GenerateProductKeysStackPanel(XNamespace ns, Product product)
        {
            return new XElement(
                ns + XamlType.StackPanel,
                new XElement(ns + XamlType.StackPanel, GenerateProductKeys(ns, product)));
        }

        /// <summary>
        /// Generates the notes stack panel.
        /// </summary>
        /// <param name="ns">The namespace.</param>
        /// <param name="product">The product.</param>
        /// <returns>The notes stack panel</returns>
        private static XElement GenerateNotesStackPanel(XNamespace ns, Product product)
        {
            Visibility showNotes = Visibility.Visible;
            if (string.IsNullOrEmpty(product.Notes))
            {
                showNotes = Visibility.Collapsed;
            }

            return new XElement(
                ns + XamlType.StackPanel,
                XamlGenerator.GenerateVisibilityAttribute(showNotes),
                XamlGenerator.GenerateOrientationAttribute(Orientation.Horizontal),
                XamlGenerator.GenerateDockPanelDockAttribute(Dock.Bottom),
                XamlGenerator.GenerateNotesLabelTextBlock(ns),
                XamlGenerator.GenerateNotesTextBlock(ns, product.Notes));
        }

        /// <summary>
        /// Generates the name stack panel.
        /// </summary>
        /// <param name="ns">The namespace.</param>
        /// <param name="product">The product.</param>
        /// <returns>The Name Stack panel</returns>
        private static XElement GenerateNameStackPanel(XNamespace ns, Product product)
        {
            return new XElement(
                ns + XamlType.StackPanel,
                XamlGenerator.GenerateOrientationAttribute(Orientation.Horizontal),
                XamlGenerator.GenerateStyleAttribute("{StaticResource PanelBackground}"),
                XamlGenerator.GenerateDockPanelDockAttribute(Dock.Top),
                XamlGenerator.GenerateNameTextBlock(ns, product.Name));
        }

        /// <summary>
        /// Generates the product keys.
        /// </summary>
        /// <param name="ns">The namespace.</param>
        /// <param name="product">The product.</param>
        /// <returns>An IEnumerable collection of XElements that make up the XAML for the products keys</returns>
        private static System.Collections.Generic.IEnumerable<XElement> GenerateProductKeys(XNamespace ns, Product product)
        {
            return from k in product.Keys
                   select new XElement(
                       ns + XamlType.StackPanel,
                       XamlGenerator.GenerateOrientationAttribute(Orientation.Horizontal),
                       new XElement(ns + XamlType.Label, XamlGenerator.GenerateStyleAttribute("{StaticResource KeyAllocToolBarLabel}"), new XAttribute("Content", "Key: ")),
                       new XElement(ns + XamlType.Label, new XAttribute("Content", k.Code)),
                       new XElement(ns + XamlType.Label, XamlGenerator.GenerateStyleAttribute("{StaticResource KeyAllocToolBarLabel}"), new XAttribute("Content", "Allocated To: ")),
                       new XElement(ns + XamlType.Label, new XAttribute("Content", k.AllocatedTo)));
        }
    }
}
